package yingyuehu.sso.helper;

import cn.hutool.core.lang.Assert;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import utils.common.StringUtils;
import yingyuehu.redis.helper.RedisHelper;
import yingyuehu.sso.enums.LoginStatus;
import yingyuehu.sso.po.LoginResult;
import yingyuehu.sso.po.LoginUser;
import yingyuehu.sso.po.UserToken;
import yingyuehu.sso.service.LoginService;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.TimeUnit;

/**
 * @program: SpringBootDemos
 * @description: 登录助手
 * @author: Kangsen
 * @create: 2022-05-20 11:41
 **/
@Component
@Slf4j
public class LoginHelper {

    /**
     * 登录用户信息key
     */
    private final String LOGIN_USER_KEY = "login:user";
    /**
     * 登录用户token
     */
    private final String LOGIN_TOKEN_KEY = "login:token";
    /**
     * 登录失败统计key
     */
    private final String LOGIN_FAIL_COUNT_KEY = "";
    /**
     * 最大登录次数
     */
    private final long MAX_FAIL_COUNT = 5;

    @Autowired
    private LoginService loginService;
    @Autowired
    private RedisHelper redisHelper;

    /**
     * 登录
     * @param account
     * @param password
     * @param callback
     * @return
     */
    public LoginResult login(String account,String password,String callback){
        Assert.notNull(account,"account is null");
        Assert.notNull(password,"password is null");
        Assert.notNull(callback,"callback is null");
        //判断账号是否多次登录被锁定
        String value = redisHelper.getStringValue(LOGIN_FAIL_COUNT_KEY + account);
        if(StringUtils.isNotBlank(value)){
            long parseLong = Long.parseLong(value);
            if(parseLong >= MAX_FAIL_COUNT){
                return LoginResult.builder().loginStatus(LoginStatus.ACCOUNT_LOCK).build();
            }
        }
        //登录操作
        LoginResult loginResult = loginService.login(account,password,callback);
        switch (loginResult.getLoginStatus()){
            case SUCCESS:
                loginSuccess(loginResult);
                break;
            case FAIL:
                loginFail(loginResult);
                break;
            case ERROR:
                loginError(loginResult);
                break;
            default:
                break;
        }
        return loginResult;
    }

    /**
     * 注销登录
     * @param account
     * @param token
     */
    public void logOut(String account,String token){
        Assert.notNull(account,"account is null");
        Assert.notNull(token,"token is null");
        removeKey(account,token);
    }

    /**
     * 注销登录
     * @param token
     */
    public void logOut(String token){
        Assert.notNull(token,"token is null");
        removeKey(token);
    }

    /**
     * 获取登录用户信息
     * @param token
     * @return
     */
    public LoginUser getLoginUser(String token){
        Assert.notNull(token,"token is null");
        String value = redisHelper.getStringValue(LOGIN_USER_KEY + token);
        if(StringUtils.isNotBlank(value)){
            return JSON.parseObject(value,LoginUser.class);
        }
        return null;
    }

    /**
     * 移除KEY
     * @param account
     * @param token
     */
    public void removeKey(String account,String token){
        redisHelper.del(LOGIN_FAIL_COUNT_KEY + account);
        redisHelper.del(LOGIN_TOKEN_KEY + account);
        redisHelper.del(LOGIN_USER_KEY + token);
    }

    /**
     * 移除key
     * @param token
     */
    public void removeKey(String token){
        redisHelper.del(LOGIN_USER_KEY + token);
        //其余的key 到达过期时间后自动删除
    }

    /**
     * 登录异常
     * @param loginResult
     */
    private void loginError(LoginResult loginResult){
        log.error("user {}  登录异常",loginResult.getLoginUser().getAccount() );
    }

    /**
     * 登录失败操作
     * @param loginResult
     */
    private void loginFail(LoginResult loginResult){
        String key = LOGIN_FAIL_COUNT_KEY + loginResult.getLoginUser().getAccount();
        redisHelper.increment(key,30 * 60 * 1000);
    }

    /**
     * 登录成功
     * @param loginResult
     */
    private void loginSuccess(LoginResult loginResult){
        LoginUser loginUser = loginResult.getLoginUser();
        loginUser.setLoginTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        UserToken userToken = UserToken.getUserToken();
        redisHelper.set(LOGIN_TOKEN_KEY + loginResult.getLoginUser().getAccount(),JSON.toJSONString(userToken),30, TimeUnit.MINUTES);
        redisHelper.set(LOGIN_USER_KEY + userToken.getToken(),JSON.toJSONString(loginUser),30,TimeUnit.MINUTES);
        redisHelper.del(LOGIN_FAIL_COUNT_KEY + loginResult.getLoginUser().getAccount());
    }

}
